package com.soyea.service;

import com.soyea.dto.WxUserDTO;
import com.soyea.entity.User;
import com.soyea.entity.UserExample;
import com.soyea.exception.BizException;
import com.soyea.mapper.UserMapper;
import com.soyea.vo.PrizeEnum;
import com.soyea.vo.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 用户 服务
 * Created by skh on 2018/1/19
 */
@Service
@Transactional
@Slf4j
public class WxUserService {

	@Autowired
	private UserMapper userMapper;

	@Autowired
	private WxMpService wxMpService;

	private Queue<User> userQueue = new ConcurrentLinkedDeque<>();

	/**
	 * 保存用户
	 *
	 * @param userDTO
	 */
	public void save(WxUserDTO userDTO) {

		//校验名字
		if (checkNameExist(userDTO.getName())) {
			throw new BizException(ResultEnum.USER_NAME_EXIST);
		}

		//校验手机号
		if (checkPhoneExist(userDTO.getPhone())) {
			throw new BizException(ResultEnum.USER_PHONE_EXIST);
		}
		if (!isMobile(userDTO.getPhone())){
			throw new BizException(ResultEnum.USER_PHONE_ERROR);
		}

		//校验openId
		if (StringUtils.isBlank(userDTO.getOpenid())) {
			log.error("[新增用户] openId为空,userDTO={}", userDTO);
			throw new BizException(ResultEnum.USER_AUTH_FAIL);
		}
		if (checkOpenIdExist(userDTO.getOpenid())) {
			throw new BizException(ResultEnum.USER_OPENID_EXIST);
		}

		//根据openId 获取用户信息
		log.info("[新增用户] openId存在,userDTO={}", userDTO);
		WxMpUser wxMpUser = null;
		try {
			//根据openId 获取用户信息(昵称和头像)
			wxMpUser = wxMpService.getUserService().userInfo(userDTO.getOpenid());
		} catch (WxErrorException e) {
			log.error("[新增用户] 获取用户信息失败,openId={}", userDTO.getOpenid(), e);
		}
		//如果用户信息获取失败,填写默认值
		if (wxMpUser == null) {
			log.error("[新增用户] 获取用户信息为空,openId={}", userDTO.getOpenid());
			throw new BizException(ResultEnum.GET_USER_INFO_FAIL);
		}

		log.info("[新增用户] 成功获取用户信息,wxMpUser={}", wxMpUser);
		//填充属性
		User user = new User();
		user.setName(userDTO.getName());
		user.setPhone(userDTO.getPhone());
		user.setDeptName(userDTO.getDeptName());
		user.setOpenid(userDTO.getOpenid());
		user.setWxName(wxMpUser.getNickname());
		user.setWxImage(wxMpUser.getHeadImgUrl());
		user.setState(PrizeEnum.NO_PRIZE.getCode());
		user.setCreateTime(new Date());

		//新增用户
		userMapper.insertSelective(user);
		log.info("[新增用户] 新增用户成功,user={}", user);

		//保存到队列中供前端获取
		boolean b = userQueue.offer(user);
		if (b) {
			log.info("[新增用户] 用户成功添加到队列,user={},当前队列大小:size={}", user, userQueue.size());
		} else {
			log.warn("[新增用户] 用户添加到队列失败,user={},当前队列大小:size={}", user, userQueue.size());
		}
	}

	//前端轮询获取队列中用户信息
	public User pollUser() {
		if (!userQueue.isEmpty()) {
			User user = userQueue.poll();
			log.info("从队列中取出用户:user={},当前队列大小:size={}", user, userQueue.size());
			return user;
		} else {
			log.info("当前用户队列为空,无法获取用户信息");
			return null;
		}
	}

	//抽奖
	public User draw(Integer prizeStatus) {
		if (prizeStatus == null) {
			throw new BizException(ResultEnum.PRIZE_STATUS_IS_NULL);
		}

		//获取所有未中奖用户列表
		List<User> noPrizeUserList = listNoPrizeUser();
		log.info("[抽奖] 获取到未中奖的用户列表:size={}", noPrizeUserList.size());


		if (noPrizeUserList.size() == 0) {
			//所有用户都已中奖
			throw new BizException(ResultEnum.USER_ALL_HAVE_PRIZE);
		}

		//使用随机算法,算出随机的集合索引
		int index = calculateRandomIndex(noPrizeUserList.size());

		//取该索引的用户,设置相应中奖等级,返回给前端.
		User user = noPrizeUserList.get(index);
		log.info("[抽奖] 中奖用户为user={}", user);
		user.setState(prizeStatus);
		user.setPrizeTime(new Date());

		//更新用户
		userMapper.updateByPrimaryKeySelective(user);

		return user;
	}

	//返回中奖人数
	public Integer countDrawPeople(Integer prizeStatus){
		if (prizeStatus == null) {
			throw new BizException(ResultEnum.PRIZE_STATUS_IS_NULL);
		}
		//获取中奖用户列表
		List<User> prizeUserList = getPrizeUserList(prizeStatus);
		log.info("[获取中奖用户人数],中奖等级prizeStatus={},中奖人数={}", prizeStatus, prizeUserList.size());
		return prizeUserList.size();
	}

	//获取中奖用户列表
	public List<User> getPrizeUserList(Integer prizeStatus) {
		if (prizeStatus == null) {
			throw new BizException(ResultEnum.PRIZE_STATUS_IS_NULL);
		}

		List<User> userList = getPrizeUsers(prizeStatus);
		log.info("[获取中奖用户列表],中奖等级prizeStatus={},中奖人数={}", prizeStatus, userList.size());

		return userList;
	}

	//查询相应中奖情况的用户列表
	public List<User> getPrizeUsers(Integer prizeStatus) {
		UserExample userExample = new UserExample();
		UserExample.Criteria criteria = userExample.createCriteria();
		criteria.andStateEqualTo(prizeStatus);
		return userMapper.selectByExample(userExample);
	}



	//随机数算法,返回集合的索引值
	public int calculateRandomIndex(int size) {
		int i = RandomUtils.nextInt(0, size);
		log.info("[随机数算法] 算出索引值为index={}", i);
		return i;
	}

	//获取未中奖的用户列表
	public List<User> listNoPrizeUser() {
		UserExample userExample = new UserExample();
		UserExample.Criteria criteria = userExample.createCriteria();
		criteria.andStateEqualTo(PrizeEnum.NO_PRIZE.getCode());
		List<User> users = userMapper.selectByExample(userExample);
		return users;
	}

	//校验名字是否重复
	public boolean checkNameExist(String name) {
		UserExample userExample = new UserExample();
		UserExample.Criteria criteria = userExample.createCriteria();
		criteria.andNameEqualTo(name);
		List<User> users = userMapper.selectByExample(userExample);
		return users.size() > 0 ? true : false;
	}

	//校验手机号是否重复
	public boolean checkPhoneExist(String phone) {
		UserExample userExample = new UserExample();
		UserExample.Criteria criteria = userExample.createCriteria();
		criteria.andPhoneEqualTo(phone);
		List<User> users = userMapper.selectByExample(userExample);
		return users.size() > 0 ? true : false;
	}

	//校验openid是否重复
	public boolean checkOpenIdExist(String openid) {
		UserExample userExample = new UserExample();
		UserExample.Criteria criteria = userExample.createCriteria();
		criteria.andOpenidEqualTo(openid);
		List<User> users = userMapper.selectByExample(userExample);
		return users.size() > 0 ? true : false;
	}


	//根据openid删除用户
	public void deleteUserByOpenid(String openid) {
		if (StringUtils.isBlank(openid)) {
			log.error("[删除用户],openid为空");
			throw new BizException(ResultEnum.PARAM_ERROR);
		}
		UserExample userExample = new UserExample();
		UserExample.Criteria criteria = userExample.createCriteria();
		criteria.andOpenidEqualTo(openid);
		userMapper.deleteByExample(userExample);
		log.info("[删除用户],openid={}的用户被删除",openid);
	}

	//查询用户列表
	public List<User> selectUserList() {
		List<User> userList = userMapper.selectByExample(null);
		log.info("[查询用户列表] 当前用户人数:{}",userList.size());
		return userList;
	}

	//校验手机号
	public static Boolean isMobile(String number) {
		boolean flag = false;
		try {
			Pattern p = Pattern.compile("^(13[0-9]|15[012356789]|17[0-9]|18[0-9]|14[57])[0-9]{8}$");
			Matcher m = p.matcher(number);
			flag = m.matches();
		} catch (Exception e) {
			log.error("手机号校验失败,number={}",number);
			flag = false;
		}
		return flag;
	}


	public void restoreUsersToNoPrize() {
		//查询所有中奖用户
		UserExample userExample = new UserExample();
		UserExample.Criteria criteria = userExample.createCriteria();
		criteria.andStateNotEqualTo(0);
		List<User> userList = userMapper.selectByExample(userExample);

		//修改中奖用户的状态为未中奖
		for (User user : userList) {
			user.setState(PrizeEnum.NO_PRIZE.getCode());
			user.setPrizeTime(null);
			userMapper.updateByPrimaryKeySelective(user);
		}

		log.info("还原用户中奖状态成功");
	}
}
